package checkers.server.logic.classes.network;

import java.net.Socket;
import java.util.ArrayList;

import checkers.common.logic.commands.AuthorizeRequest;
import checkers.common.logic.commands.AuthorizeResponse;
import checkers.common.logic.commands.Command;
import checkers.common.logic.commands.CreateGameRequest;
import checkers.common.logic.commands.CreateGameResponse;
import checkers.common.logic.commands.EnemyMoveRequest;
import checkers.common.logic.commands.EnemyMoveResponse;
import checkers.common.logic.commands.JoinGameRequest;
import checkers.common.logic.commands.JoinGameResponse;
import checkers.common.logic.commands.ListRequest;
import checkers.common.logic.commands.ListResponse;
import checkers.common.logic.commands.MoveRequest;
import checkers.common.logic.commands.MoveResponse;
import checkers.common.logic.commands.RegisterRequest;
import checkers.common.logic.commands.RegisterResponse;
import checkers.server.logic.classes.Game;
import checkers.server.logic.classes.Player;
import checkers.server.logic.classes.GameContext;

public class ListenToClient implements Runnable {
	
	private Socket socket;
	
	public ListenToClient(Socket socket){
		this.socket = socket;
	}

	private void handleCommand(RegisterRequest regRequest) throws Exception {
		RegisterResponse rResponse = new RegisterResponse();
		if (GameContext.getInstance().getRegistrator().register(regRequest)) {
			rResponse.setCheckRegister(1);
		} else {
			rResponse.setCheckRegister(0);
		}

	    GameContext.getInstance().getNetlayer().sendCommand(rResponse, socket);
	}
	
	private void handleCommand(AuthorizeRequest aRequest) throws Exception {
		AuthorizeResponse aResponse = new AuthorizeResponse();
		//if (!GameContext.getInstance().getRegistrator().isRegistered(aRequest)) {
			//aResponse.setCheckAuthorize(0);
			//aResponse.setReason("Player not registered!");
		//} else {
			Player player = new Player();
			player.setLogin(aRequest.getLogin());
			GameContext.getInstance().addPlayer(player);
			aResponse.setCheckAuthorize(1);
			aResponse.setPlayerId(player.getId());
		//}
		
	    GameContext.getInstance().getNetlayer().sendCommand(aResponse, socket);
	}
	
	private void handleCommand(ListRequest lRequest) throws Exception {
		ListResponse lResponse = new ListResponse();
		ArrayList<Game> games = GameContext.getInstance().getAvailibleGames();
		
		int[] side = new int[games.size()];
		int[] ids = new int[games.size()];
		String[] pl = new String[games.size()];
		for (int i = 0; i < games.size(); i++) {
			pl[i] = games.get(i).getPlayerOne().getLogin();
			side[i] = games.get(i).getPlayerOne().getColor();
			ids[i] = games.get(i).getId();
		}
		lResponse.setSides(side);
		lResponse.setNames(pl);	
		lResponse.setGamesID(ids);
		
		GameContext.getInstance().getNetlayer().sendCommand(lResponse, socket);
	}
	
	private void handleCommand(CreateGameRequest gRequest) throws Exception {
		CreateGameResponse gResponse = new CreateGameResponse();
		Player player = GameContext.getInstance().getPlayerById(gRequest.getPlayerID());
		if (player != null) {
			player.setColor(gRequest.getSide());
			Game game = new Game(player);
			GameContext.getInstance().addGame(game);
			gResponse.setIsGameCreated(1);
			gResponse.setGameID(game.getId());
		} else {
			gResponse.setIsGameCreated(0);
		}
		
		GameContext.getInstance().getNetlayer().sendCommand(gResponse, socket);
	}
	
	private void handleCommand(JoinGameRequest jRequest) throws Exception {
		JoinGameResponse jResponse = new JoinGameResponse();
		Game game = GameContext.getInstance().getGameById(jRequest.getGameID());
		if (!game.checkStart()) {
			game.addPlayer(GameContext.getInstance().getPlayerById(jRequest.getPlayerID()));
			jResponse.setJoiningSuccess(1);
			game.startGame();
		} else {
			jResponse.setJoiningSuccess(0);
		}
		
		GameContext.getInstance().getNetlayer().sendCommand(jResponse, socket);	
	}
	
	private void handleCommand(EnemyMoveRequest eRequest) throws Exception {
		Player player = GameContext.getInstance().getPlayerById(eRequest.getPlayerID());
		Game game = GameContext.getInstance().getGameById(eRequest.getGameID());
		while (game.getCurrentPlayer() != player);
		EnemyMoveResponse eResponse = new EnemyMoveResponse();
		eResponse.setStep(game.getLastMove());
		GameContext.getInstance().getNetlayer().sendCommand(eResponse, socket);
	}
	
	private void handleCommand(MoveRequest mRequest) throws Exception {
		Player player = GameContext.getInstance().getPlayerById(mRequest.getPlayerId());
		MoveResponse mResponse = new MoveResponse();
		Game game = GameContext.getInstance().getGameById(mRequest.getGameId());
		if ((game.checkMoves(player, mRequest.getStep())) && (game.getCurrentPlayer() == player) && (game.checkStart())){
			mResponse.setCheckMove(1);
		} else {
			mResponse.setCheckMove(0);
		}
		GameContext.getInstance().getNetlayer().sendCommand(mResponse, socket);
		game.changePlayer();
	}
	
	@Override
	public void run() {
		try {			
			Command command = GameContext.getInstance().getNetlayer().startReceivingCommand(socket);
			
			switch (command.getId()) {
				case 0:
					handleCommand((AuthorizeRequest)command);
					break;
				case 2:
					handleCommand((RegisterRequest)command);
					break;
				case 4:
					handleCommand((MoveRequest)command);
					break;
				case 8:
					handleCommand((ListRequest)command);
					break;
				case 12:
					handleCommand((CreateGameRequest)command);
					break;
				case 10:
					handleCommand((JoinGameRequest)command);
					break;
				case 14:
					handleCommand((EnemyMoveRequest)command);
					break;
			}
			socket.close();
		}
		catch (Exception e) {
			GameContext.getInstance().getLogger().addMessage(e.getMessage());
		}
	}
	
}
